package com.dragon.english_practice_back.service.impl;


import cn.hutool.core.lang.Validator;
import com.dragon.english_practice_back.entity.LoginUserDetails;
import com.dragon.english_practice_back.entity.Role;
import com.dragon.english_practice_back.entity.User;
import com.dragon.english_practice_back.enums.RedisPrefixEnum;
import com.dragon.english_practice_back.mapper.RoleMapper;
import com.dragon.english_practice_back.mapper.UserMapper;
import com.dragon.english_practice_back.reponse.Result;
import com.dragon.english_practice_back.service.LoginService;
import com.dragon.english_practice_back.util.JWTUtil;
import com.dragon.english_practice_back.util.PasswordUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    AuthenticationManager authenticate;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private AuthenticationUtilImpl authenticationUtil;
    @Override
    public Result login(User user) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
                =new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
        Authentication authentication = this.authenticate.authenticate(usernamePasswordAuthenticationToken);

        LoginUserDetails loginUserDetails = (LoginUserDetails) authentication.getPrincipal();

        int id = loginUserDetails.getUser().getId();

        //将用户信息存入redis
        authenticationUtil.cacheUserData(loginUserDetails);

        //制作token
        Map<String, String> map = new HashMap<>();
        map.put("id", String.valueOf(id));
        String token = JWTUtil.createToken(map);
        //将token存入redis
        stringRedisTemplate.opsForValue().set(RedisPrefixEnum.ACCESS_TOKEN.getPrefix()+id, token);
        //创建返回数据
        Map<String, String> mapR = new HashMap<>();
        mapR.put("token", token);
        log.info("id:{} login succeed", id);
        return Result.ok("login succeed", mapR);
    }

    @Override
    public Result logout() {
        // 用户登出
        // 1. 获取当前用户的 ID
        int id = authenticationUtil.id();
        // 2. 清除 Redis 中的用户信息
        authenticationUtil.unCacheUserData();
        stringRedisTemplate.delete(RedisPrefixEnum.ACCESS_TOKEN.getPrefix()+id);
        log.info("id:{} logout succeed", id);
        return Result.ok("logout succeed");
    }

    @Override
    public boolean existEmail(String email) {
        // 检查邮箱是否已存在
        // 1. 从数据库查询用户信息
        List<Integer> ids = userMapper.selectByEmail(email);
        if (!ids.isEmpty()){
            return true;
        }
        // 2. 如果用户存在，返回 true；否则，返回 false
        return false;
    }

    @Override
    public List<Role> role() {
        // 获取角色列表
        List<Role> roles = roleMapper.rolesByUserId(authenticationUtil.id());
        return roles;
    }

    @Transactional
    @Override
    public Result register(User user) {
        // 注册逻辑
        // 1. 检查用户邮箱是否已存在
        // 检查数据
        if (!Validator.isEmail(user.getEmail()))
            return Result.no("邮箱格式错误");
        if (user.getPassword().length() < 6)
            return Result.no("密码长度小于6");
        if (this.existEmail(user.getEmail())){
            return Result.no("邮箱已存在");
        }
        // 2. 插入用户信息到数据库
        User insertUser = new User();
        // 将id设为null
        insertUser.setId(null);
        insertUser.setEmail(user.getEmail());
        // 密码加密
        String encryptPassword = PasswordUtil.encode(user.getPassword());
        insertUser.setPassword(encryptPassword);
        insertUser.setName(user.getName());
        // 检查是否有name
        if (insertUser.getName() == null){
            insertUser.setName(insertUser.getEmail());
        }
        // 插入用户信息到数据库
        int checkInsert = userMapper.insert(insertUser);
        if (checkInsert == 0){
            return Result.no("注册失败");
        }
        // 取出id
        int id = userMapper.selectByEmail(insertUser.getEmail()).get(0);
        insertUser.setId(id);
        // 插入用户角色
        roleMapper.setUserRole(insertUser.getId());
        // 密码设为null返回给前端
        insertUser.setPassword(null);
        // 3. 返回注册结果
        return Result.ok("注册成功", insertUser);

    }

}
